
local WatchValue = commonlib.inherit(nil);
function NewWatchValue(value, watch_object, watch_object_key)
    local metatable = {};
    metatable.m_value = value;
    metatable.m_watch_object = watch_object;
    metatable.m_watch_object_key = watch_object_key;
    metatable.__index = function(self, key)
        if (key == "__is_watch_value__") then return true end

        if (type(metatable.m_value) == "table") then
            return metatable.m_value[key];
        else
            return metatable.m_value;
        end
    end
    metatable.__newindex = function(self, key, value)
        if (key == "__is_watch_value__") then return end

        if (type(metatable.m_value) == "table") then
            metatable.m_value[key] = value;
        else
            metatable.m_value = value;
        end
    end
    return setmetatable({}, metatable);
end

local WatchExpr = commonlib.inherit(nil);

function WatchExpr:ctor()
    self.m_watch_expr = nil;                    -- 表达试
    self.m_callback = nil;                      -- 值回调
    self.m_root_watch_object = nil;             -- 表达式环境
    self.m_depend_watch_object_key_map = {};    -- 依赖项
    self.m_old_value = nil;                     -- 旧值
    self.m_new_value = nil;                     -- 新值

    -- 依赖项更新回调
    local __self__ = self;
    self.m_watch_object_key_callback = function()
        __self__.m_root_watch_object:RemoveWatchObjectKeyCallback(__self__.m_depend_watch_object_key_map, __self__.m_watch_object_key_callback);

        -- 调用表达式
        __self__.m_new_value, __self__.m_depend_watch_object_key_map = __self__.m_watch_object:DoString(__self__.m_watch_expr);

        __self__.m_root_watch_object:AddWatchObjectKeyCallback(__self__.m_depend_watch_object_key_map, __self__.m_watch_object_key_callback);

        -- 值相同直接返回 不同更新值并回调表达式
        if (__self__.m_new_value == __self__.m_old_value) then return end
        __self__.m_old_value = __self__.m_new_value;

        -- 表达式回调
        if (type(__self__.m_callback) == "function") then
            (__self__.m_callback)(__self__.m_new_value);
        end
    end
end

function WatchExpr:Init(root_watch_object, watch_object, watch_expr, callback, old_value)
    self.m_root_watch_object = root_watch_object;
    self.m_watch_object = watch_object;
    self.m_watch_expr = "return " .. watch_expr;
    self.m_callback = callback;
    self.m_old_value = old_value;

    self.m_watch_object_key_callback();

    return self;
end

function WatchExpr:Destroy()
    self.m_root_watch_object:RemoveWatchObjectKeyCallback(self.m_depend_watch_object_key_map, self.m_watch_object_key_callback);
end

local WatchObject = commonlib.inherit(nil);

function WatchObject:ctor()
    self.m_key_instance = nil;           -- 所在观察对象实例
    self.m_key_instance_key = nil;       -- 所在观察对象实例键key对应的值
    self.m_data = nil;                   -- 观察对象数据
    self.m_instance = nil;               -- 实例
    self.m_metatable = nil;              -- 实例元素
    self.m_root_watch_object = nil;      -- 根监控对象
    self.m_watch_exprs = {};             -- 监控表达式
end

function WatchObject:Init(data, inherit_watch_object, key_instance, key_instance_key, root_watch_object)
    local __self__ = self;                                        -- __self__ ~= WatchObject 是 WatchObject 真实实例
    local metatable = {};
    local instance = setmetatable({}, metatable);

    __self__.m_data = {};
    __self__.m_inherit_watch_object = inherit_watch_object or {};
    __self__.m_instance = instance;
    __self__.m_metatable = metatable;
    __self__.m_key_instance = key_instance;
    __self__.m_key_instance_key = key_instance_key;
    __self__.m_root_watch_object = root_watch_object;

    local index_callback = __self__.m_root_watch_object.m_index_callback;
    local newindex_callback = __self__.m_root_watch_object.m_newindex_callback;
    -- 读索引
    metatable.__index = function(_, key)
        -- 回去实例环境
        if (key == nil) then return nil end
        if (key == "__self__") then return __self__ end
        if (key == "__is_watch_object__") then return true end

        -- 触发读回调
        local instance_self = __self__;
        local instacne_self_key = key;
        while (instance_self ~= nil and instacne_self_key ~= nil) do
            index_callback(instance_self, instacne_self_key);
            instacne_self_key = instance_self.m_key_instance_key;                                          -- 实例所在实例的Key值
            instance_self = instance_self.m_key_instance and instance_self.m_key_instance.__self__;        -- 实例所在实例的WatchObject值
        end

        local value = __self__.m_data[key];
        -- if (type(value) == "table" and value.__is_watch_value__) then return value.value end

        if (value ~= nil) then return value end
        
        return __self__.m_inherit_watch_object[key];
    end

    -- 写索引
    metatable.__newindex = function(_, key, val)
        -- 内置Key不支持更改
        if (key == "__self__" or key == "__is_watch_object__" or key == nil) then return end
        -- if (type(val) == "table" and val.__is_watch_value__) then val = val.value end

        -- 获取新旧值
        local old_val = instance[key];
        local new_val = val;

        -- 普通表转成WatchObject值
        if (type(val) == "table" and not val.__is_watch_object__) then
            local watch_object = WatchObject:new():Init(val, nil, instance, key, root_watch_object);
            new_val = watch_object:GetWatchData();
        end

        -- 如果值相同则直接返回
        if (old_val == new_val) then return end

        -- 赋值新值
        __self__.m_data[key] = new_val;

        -- 触发写回调  是否触发父回调
        newindex_callback(__self__, key, new_val, old_val);
    end

    metatable.__len = function(_)
        return #(__self__.m_data);
    end

    metatable.__pairs = function(_)
        return pairs(__self__.m_data);
    end

    -- 拷贝data 支持表递归嵌套
    if (type(data) == "table") then
        local cache_table = {}
        cache_table[data] = self;
        for key, val in pairs(data) do
            if (type(val) == "table") then
                if (not cache_table[val]) then
                    instance[key] = val;
                    cache_table[val] = instance[key];
                end
            else 
                instance[key] = val;
            end
        end
    end

    return self;
end

function WatchObject:GetRawData()
    return self.m_data;
end

function WatchObject:GetWatchData()
    return self.m_instance
end

function WatchObject:GetInstance()
    return self.m_instance;
end

function WatchObject:GetEnv()
    return self.m_instance;
end

function WatchObject:Set(key, value)
    self.m_instance[key] = value;
end

function WatchObject:Get(key)
    return self.m_instance[key];
end

function WatchObject:Watch(expr, callback)
    self.m_watch_exprs[callback] = self:NewWatchExpr(expr, callback);
end

function WatchObject:GetRootWatchObject()
    return self.m_root_watch_object;
end

function WatchObject:DoString(text)
    return self.m_root_watch_object:DoString(text, self.m_instance);
end

-- 新建一个监控表达式
function WatchObject:NewWatchExpr(watch_expr, callback, value)
    return WatchExpr:new():Init(self.m_root_watch_object, self, watch_expr, callback, value);
end

-- 新建新继承监控对象
function WatchObject:NewInheritWatchObject(data)
    return WatchObject:new():Init(data, self:GetWatchData(), nil, nil, self:GetRootWatchObject());
end

local RootWatchObject = commonlib.inherit(WatchObject);

function RootWatchObject:ctor()
    -- 读索引集
    self.m_watch_object_index_key_map = nil;
    -- 写索引集
    self.m_watch_object_newindex_key_map = {};
    -- 索引回调集
    self.m_watch_object_key_callback_map = {};
    -- 是否自动监控触发回调
    self.m_auto_trigger_watch_expr_callback = true;
end

function RootWatchObject:SetAutoTriggerWatchExprCallback(auto_trigger_watch_expr_callback)
    self.m_auto_trigger_watch_expr_callback = auto_trigger_watch_expr_callback;
end

function RootWatchObject:Init(data, G)
    local __self__ = self;
    self.m_index_callback = function(watch_object, key)
        -- print("index_callback", watch_object);
        if (not __self__.m_watch_object_index_key_map) then return end
        __self__.m_watch_object_index_key_map[watch_object] = self.m_watch_object_index_key_map[watch_object] or {};
        __self__.m_watch_object_index_key_map[watch_object][key] = { watch_object = watch_object, key = key};
    end

    self.m_newindex_callback = function(watch_object, key, new_val, old_val)
        -- print("newindex_callback", watch_object, key, new_val, old_val);
        __self__.m_watch_object_newindex_key_map[watch_object] = __self__.m_watch_object_newindex_key_map[watch_object] or {};
        __self__.m_watch_object_newindex_key_map[watch_object][key] = { watch_object = watch_object, key = key, new_val = new_val, old_val = old_val};

        if (__self__.m_auto_trigger_watch_expr_callback) then
            __self__:TriggerWatchExprCallback();
        end
    end

    RootWatchObject._super.Init(self, data, G, nil, nil, self);

    return self;
end

-- 移除新依赖回调
function RootWatchObject:RemoveWatchObjectKeyCallback(watch_object_key_map, callback)
    for watch_object, key_map in pairs(watch_object_key_map) do
        local key_callback_map = self.m_watch_object_key_callback_map[watch_object];
        if (key_callback_map) then
            for key in pairs(key_map) do
                local callback_map = key_callback_map[key];
                if (callback_map) then
                    callback_map[callback] = nil;
                end
            end
        end
    end
end

-- 注册新依赖回调
function RootWatchObject:AddWatchObjectKeyCallback(watch_object_key_map, callback)
    for watch_object, key_map in pairs(watch_object_key_map) do
        local key_callback_map = self.m_watch_object_key_callback_map[watch_object] or {};
        for key in pairs(key_map) do
            key_callback_map[key] = key_callback_map[key] or {};
            key_callback_map[key][callback] = callback;
        end
        self.m_watch_object_key_callback_map[watch_object] = key_callback_map;
    end
end

-- 执行字符串代码
function RootWatchObject:DoString(text, env)
    local old_watch_object_index_key_map = self.m_watch_object_index_key_map;
    -- 清空读索引集
    self.m_watch_object_index_key_map = {};
    -- 执行字符串代码
    local value = commonlib.dostring(text, env or self.m_instance);
    -- 缓存读索引集
    local depend_watch_object_key_map = self.m_watch_object_index_key_map;
    -- 还原读索引
    self.m_watch_object_index_key_map = old_watch_object_index_key_map;
    -- 返回值和读索引集
    return value, depend_watch_object_key_map;
end

-- 触发值更新回调
function RootWatchObject:TriggerWatchExprCallback()
    local cur_watch_object_newindex_key_map = self.m_watch_object_newindex_key_map;
    self.m_watch_object_newindex_key_map = {};
    self.m_watch_object_index_key_map = nil;
    for watch_object, key_map in pairs(cur_watch_object_newindex_key_map) do
        local key_callback_map = self.m_watch_object_key_callback_map[watch_object];
        if (key_callback_map) then
            for key in pairs(key_map) do
                local callback_map = key_callback_map[key];
                if (callback_map) then
                    for callback in pairs(callback_map) do
                        callback();
                    end
                end
            end
        end
    end
end

function commonlib.NewRootWatchObject(data)
    return RootWatchObject:new():Init(data);
end

return RootWatchObject;

-- local watch_object = commonlib.NewRootWatchObject();
-- watch_object:NewWatchExpr("return a + b", function(expr_value)
--     print("expr_value", expr_value);
-- end);
-- watch_object:Set("a", 1);
-- watch_object:Set("b", 2);
-- print("=======", watch_object:Get("b"))